﻿using Furion;
using Furion.Authorization;
using Furion.DataEncryption;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using System.Security.Claims;
using System.Threading.Tasks;
using BaseNet.Entity.System;

namespace BaseNet.Web.Core
{
    public class JwtHandler : AppAuthorizeHandler
    {
        /// <summary>
        /// 重写 Handler 添加自动刷新收取逻辑
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task HandleAsync(AuthorizationHandlerContext context)
        {
            // 自动刷新 token
            if (JWTEncryption.AutoRefreshToken(context, context.GetCurrentHttpContext()))
            {
                await AuthorizeHandleAsync(context);
            }
            else context.Fail();    // 授权失败
        }

        public override async Task<bool> PipelineAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
        {
            return await CheckAuthorzieAsync(httpContext);
        }

        /// <summary>
        /// 检查权限
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        private async Task<bool> CheckAuthorzieAsync(DefaultHttpContext httpContext)
        {
            // 获取权限特性
            var securityDefineAttribute = httpContext.GetMetadata<SecurityDefineAttribute>();
            if (securityDefineAttribute == null) return true;

            //获取当前登录人
            var userId = App.User?.FindFirstValue("UserId");

            var sqlSugarRepository = App.GetService<ISqlSugarRepository>();
            var _db = sqlSugarRepository.Context;

            // 解析服务
            var roleIds = await _db.Queryable<SysUserRoleEntity>()
                .Where(o => o.UserId == userId)
                .Select(o => o.RoleId)
                .Distinct()
                .ToListAsync();
            var securityList = await _db.Queryable<SysRoleSecurityEntity>()
                .Where(o => roleIds.Contains(o.RoleId))
                .Select(o => o.Security)
                .Distinct()
                .ToListAsync();

            // 检查授权
            return securityList.Contains(securityDefineAttribute.ResourceId);
        }
    }
}